package com.css.upms.biz.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.css.common.core.constent.CommonConstant;
import com.css.common.core.utils.R;
import com.css.common.core.utils.tree.TreeNode;
import com.css.common.security.utils.SecurityUtil;
import com.css.lion.optlog.agent.annotation.OptLog;
import com.css.upms.api.dto.MenuDTO;
import com.css.upms.api.dto.MenuTree;
import com.css.upms.api.entity.SysMenu;
import com.css.upms.api.entity.SysRole;
import com.css.upms.api.entity.SysRoleMenu;
import com.css.upms.api.vo.MenuVo;
import com.css.upms.api.vo.TreeUtil;
import com.css.upms.biz.service.SysMenuService;
import com.css.upms.biz.service.SysRoleMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单管理
 *
 * @author hanyx
 * @date 2019-05-03 01:52:44
 */
@RestController
@AllArgsConstructor
@RequestMapping("/menu")
@Api(value = "/menu", tags = {"UPMS-菜单管理"})
@Slf4j
public class MenuController {

    private final SysMenuService menuService;

    private final SysRoleMenuService roleMenuService;

    /**
     * 通过id查询单条记录
     *
     * @param menuId
     * @return R
     */
    @ApiOperation(value = "通过id查询单条记录")
    @GetMapping("/{menuId}")
    public R<SysMenu> getById(@PathVariable("menuId") String menuId) {
        if (StringUtils.isBlank(menuId)) {
            return R.buildError("菜单id不能为空");
        }
        return new R<>(menuService.getById(menuId));
    }

    /**
     * 新增记录
     *
     * @param menu
     * @return R
     */
    @ApiOperation(value = "新增菜单管理")
    @OptLog(desc = "菜单管理", opt = "新增菜单")
    @PostMapping
//  @PreAuthorize("hasAuthority('biz_menu_add')")
    public R save(@RequestBody SysMenu menu) {
        return menuService.saveMenu(menu);
    }

    /**
     * 修改记录
     *
     * @param menu
     * @return R
     */
    @ApiOperation(value = "修改菜单管理")
    @OptLog(desc = "菜单管理", opt = "修改菜单")
    @PutMapping
//  @PreAuthorize("hasAuthority('biz_menu_edit')")
    public R update(@RequestBody SysMenu menu) {
        return menuService.updateMenuById(menu);
    }

    /**
     * 通过id删除一条记录
     *
     * @param menuId
     * @return R
     */
    @ApiOperation(value = "删除菜单")
    @OptLog(desc = "菜单管理", opt = "删除菜单")
    @DeleteMapping("/{menuId}")
//  @PreAuthorize("@hasAuthority('biz_menu_del')")
    public R removeById(@PathVariable String menuId) {
        if (StringUtils.isBlank(menuId)) {
            return R.buildError("菜单id不能为空");
        }
        return menuService.removeMenuById(menuId);
    }


    @ApiOperation(value = "删除角色菜单关系表")
    @OptLog(desc = "菜单管理", opt = "删除角色菜单关系表")
    @DeleteMapping("/role-menu/{menuId}")
//  @PreAuthorize("@hasAuthority('biz_menu_del')")
    public R removeRoleMenuById(@PathVariable String menuId) {
        if (StringUtils.isBlank(menuId)) {
            return R.buildError("菜单id不能为空");
        }
        return R.buildSuccess(roleMenuService.remove(Wrappers.<SysRoleMenu>query().lambda().eq(SysRoleMenu::getMenuId, menuId)));
    }

    /**
     * 通过ids删除多条记录
     *
     * @param menuIds
     * @return R
     */
    @ApiOperation(value = "删除菜单管理")
    @OptLog(desc = "菜单管理", opt = "批量删除菜单")
    @DeleteMapping("/batch/{menuIds}")
//  @PreAuthorize("@hasAuthority('biz_menu_del')")
    public R removeByIds(@PathVariable String menuIds) {
        if (StringUtils.isBlank(menuIds)) {
            return R.buildError("菜单ID不能为空");
        }
        return menuService.removeMenuByIds(menuIds);
    }

    /**
     * 返回当前用户的树形菜单集合
     *
     * @return 当前用户的树形菜单
     */
    @ApiOperation(value = "当前用户的树形菜单集合 - 树对象list结构")
    @GetMapping
    public R getUserMenu() {
        return new R<>(menuService.getCurrentUserMenuTree());
    }

    /**
     * 返回树形菜单集合
     *
     * @return 树形菜单
     */
    @ApiOperation(value = "返回所有树形菜单 - 树结构")
    @GetMapping(value = "/tree")
    public R getTree() {
        return new R<>(TreeUtil.buildTree(menuService.list(new QueryWrapper<SysMenu>().orderByAsc("ORDER_NUM")), CommonConstant.ROOT_NODE_VAL));
    }

    @ApiOperation(value = "返回指定菜单 - list结构")
    @GetMapping(value = "/list")
    public R getMenuList(MenuDTO menuDTO) {
        if (menuDTO == null) {
            return this.getTree();
        }
        LambdaQueryWrapper<SysMenu> wrapper = Wrappers.<SysMenu>query().lambda();
        if (StringUtils.isNotBlank(menuDTO.getMenuName())) {
            wrapper.like(SysMenu::getMenuName, menuDTO.getMenuName());
        }
        if (StringUtils.isNotBlank(menuDTO.getUrl())) {
            wrapper.like(SysMenu::getUrl, menuDTO.getUrl());
        }
        wrapper.orderByAsc(SysMenu::getOrderNum);
        return new R<>(TreeUtil.buildMenuLIst(menuService.list(wrapper)));
    }

    /**
     * 返回角色的菜单id集合
     *
     * @param roleId 角色ID
     * @return 属性集合
     */
    @ApiOperation(value = "返回指定角色的菜单id集合 - list结构")
    @GetMapping("/ids/{roleId}")
    public R getMenuIdsByRole(@PathVariable String roleId) {
        if (StringUtils.isBlank(roleId)) {
            return R.buildError("角色ID不能为空");
        }
        return R.builder().data(menuService.getMenuByRoleId(roleId)
                .stream()
                .map(MenuVo::getMenuId)
                .collect(Collectors.toList())).build();
    }


    @ApiOperation(value = "获取指定角色菜单 - 树结构")
    @GetMapping("/tree/{roleIds}")
    public R getTreeByRoleId(@PathVariable String roleIds) {
        if (StringUtils.isBlank(roleIds)) {
            return R.buildSuccess(Boolean.FALSE);
        }
        return menuService.getMenuTreeByRole(roleIds);
    }


    //    @SuppressWarnings("rawtypes")
//    @ApiOperation(value = "返回当前角色的菜单树")
//    @GetMapping("/meunTree/{roleId}")
    public R getRoleMenuTree(@PathVariable String roleId) {
        List<MenuTree> allTree = TreeUtil.buildTree(menuService.list(new QueryWrapper<SysMenu>().orderByAsc("ORDER_NUM"))
                , CommonConstant.ROOT_NODE_VAL);
        List<String> menuList = menuService.getMenuByRoleId(roleId).stream().map(MenuVo::getMenuId)
                .collect(Collectors.toList());
        List<TreeNode> treeRes = new ArrayList<TreeNode>();
        for (int i = 0; i < allTree.size(); i++) {
            MenuTree oneTree = allTree.get(i);
            TreeNode oneTreeRes = menuRecursion(oneTree, menuList);
            if (oneTreeRes != null) {
                treeRes.add(oneTreeRes);
            }
        }
        //把树的数据转化成List数据-------------------------------------------
        List<String> resNodeList = new ArrayList<String>();
        for (TreeNode nodeOne : treeRes) {
            resNodeList = getMenuList(nodeOne, resNodeList);
        }
        //获取最终想要的那个树形结构
        List<MenuTree> resTree = TreeUtil.buildTree(menuService.list(new QueryWrapper<SysMenu>().
                in("MENU_ID", resNodeList).orderByAsc("ORDER_NUM")), CommonConstant.ROOT_NODE_VAL);


        return new R<>(resTree);
    }

    private List<String> getMenuList(TreeNode node, List<String> list) {
        if (node != null && node.getChildren() != null && node.getChildren().size() > 0) {
            for (TreeNode nodeTemp : node.getChildren()) {
                list = getMenuList(nodeTemp, list);
            }
        }
        if (node != null) {
            list.add(node.getId());
        }
        return list;
    }


    /**
     * 递归创建所需要的数据
     *
     * @param tree
     * @param menuList
     * @return
     */
    private TreeNode menuRecursion(TreeNode tree, List<String> menuList) {
        boolean existsFlag = false;
        TreeNode treeRes = new TreeNode();
        BeanUtils.copyProperties(tree, treeRes);
        treeRes.setChildren(new ArrayList<TreeNode>());
        if (tree != null && tree.getChildren() != null && tree.getChildren().size() > 0) {
            for (TreeNode temp : tree.getChildren()) {
                TreeNode tempNode = menuRecursion(temp, menuList);
                if (tempNode != null) {
                    existsFlag = true;
                    List<TreeNode> treeNodeListTemp = treeRes.getChildren();
                    treeNodeListTemp.add(tempNode);
                    treeRes.setChildren(treeNodeListTemp);
                }
            }
        }

        if (tree != null && menuList.contains(tree.getId())) {
            existsFlag = true;
        }
        if (existsFlag) {
            return treeRes;
        }
        return null;
    }


}
